package com.jialanmo.helper.recyclerview;

import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public final class CheckableAdapter<T> extends BaseAdapter<T> {

    public final static int CHOICE_MODE_NONE = 0;
    public final static int CHOICE_MODE_SINGLE = 1;
    public final static int CHOICE_MODE_MULTIPLE = 2;

    private final BaseAdapter<T> mOriginalAdapter;

    private int mChoiceMode;
    private final Set<Integer> mChoicePositions = new HashSet<>();

    private boolean mIsHeaderViewChecked;
    private boolean mIsFooterViewChecked;

    public CheckableAdapter(BaseAdapter<T> adapter) {
        mOriginalAdapter = adapter;
    }

    @Override
    public List<T> getData() {
        return mOriginalAdapter.getData();
    }

    @Override
    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener, int offset) {
        mOriginalAdapter.setOnLoadMoreListener(onLoadMoreListener, offset);
    }

    public void setChoiceMode(int choiceMode) {
        if (choiceMode != CHOICE_MODE_NONE && choiceMode != CHOICE_MODE_SINGLE && choiceMode != CHOICE_MODE_MULTIPLE) {
            throw new RuntimeException("错误的choiceMode");
        }
        //原来是多选,现在改成单选,且有大于1项被选中,则清空选中项
        if (mChoiceMode == CHOICE_MODE_MULTIPLE && choiceMode == CHOICE_MODE_SINGLE && mChoicePositions.size() > 1) {
            mChoicePositions.clear();
            notifyDataSetChanged();
        }
        mChoiceMode = choiceMode;
    }

    public boolean isItemChecked(int position) {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        return mChoicePositions.contains(position);
    }

    public List<Integer> getCheckedItems() {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        List<Integer> data = new ArrayList<>();
        for (Integer mChoicePosition : mChoicePositions) {
            data.add(mChoicePosition);
        }
        return data;
    }

    public void setItemChecked(int position, boolean checked) {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        if (position < 0 || position >= getDataCount()) {
            throw new RuntimeException("position超出取值范围");
        }
        if (mChoiceMode == CHOICE_MODE_SINGLE) {
            int oldPosition = getOldChoicePosition();
            if (checked && position != oldPosition) {
                if (oldPosition != -1) {
                    mChoicePositions.remove(oldPosition);
                    notifyItemChanged(getRealPosition(oldPosition));
                }
                if (mIsHeaderViewChecked) {
                    setHeaderViewChecked(false);
                }
                if (mIsFooterViewChecked) {
                    setFooterViewChecked(false);
                }
                mChoicePositions.add(position);
                notifyItemChanged(getRealPosition(position));
            } else if (!checked && position == oldPosition) {
                mChoicePositions.remove(position);
                notifyItemChanged(getRealPosition(position));
            }
        } else {
            if (checked) {
                mChoicePositions.add(position);
            } else {
                mChoicePositions.remove(position);
            }
            notifyItemChanged(getRealPosition(position));
        }
    }

    public boolean isHeaderViewChecked() {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        if (!isHeaderAndFooterAdapter() || !getHeaderAndFooterAdapter().hasHeaderView()) {
            throw new RuntimeException("未设置headerView");
        }
        return mIsHeaderViewChecked;
    }

    public void setHeaderViewChecked(boolean checked) {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        if (!isHeaderAndFooterAdapter() || !getHeaderAndFooterAdapter().hasHeaderView()) {
            throw new RuntimeException("未设置headerView");
        }
        if (mChoiceMode == CHOICE_MODE_SINGLE) {
            int oldPosition = getOldChoicePosition();
            if (checked && !mIsHeaderViewChecked) {
                mIsHeaderViewChecked = true;
                notifyItemChanged(0);
                if (oldPosition != -1) {
                    mChoicePositions.remove(oldPosition);
                    notifyItemChanged(getRealPosition(oldPosition));
                }
            } else if (!checked && mIsHeaderViewChecked) {
                mIsHeaderViewChecked = false;
                notifyItemChanged(0);
            }
        } else if (mIsHeaderViewChecked != checked) {
            mIsHeaderViewChecked = checked;
            notifyItemChanged(0);
        }
    }

    public boolean isFooterViewChecked() {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        if (!isHeaderAndFooterAdapter() || !getHeaderAndFooterAdapter().hasFooterView()) {
            throw new RuntimeException("未设置footerView");
        }
        return mIsFooterViewChecked;
    }

    public void setFooterViewChecked(boolean checked) {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        if (!isHeaderAndFooterAdapter() || !getHeaderAndFooterAdapter().hasFooterView()) {
            throw new RuntimeException("未设置footerView");
        }
        if (mChoiceMode == CHOICE_MODE_SINGLE) {
            int oldPosition = getOldChoicePosition();
            if (checked && !mIsFooterViewChecked) {
                mIsFooterViewChecked = true;
                notifyItemChanged(getItemCount() - 1);
                if (oldPosition != -1) {
                    mChoicePositions.remove(oldPosition);
                    notifyItemChanged(getRealPosition(oldPosition));
                }
            } else if (!checked && mIsFooterViewChecked) {
                mIsFooterViewChecked = false;
                notifyItemChanged(getItemCount() - 1);
            }
        } else if (mIsFooterViewChecked != checked) {
            mIsFooterViewChecked = checked;
            notifyItemChanged(getItemCount() - 1);
        }
    }

    public void clearItemChecked() {
        if (mChoiceMode == CHOICE_MODE_NONE) {
            throw new RuntimeException("还未设置choiceMode");
        }
        Iterator<Integer> iterator = mChoicePositions.iterator();
        while (iterator.hasNext()) {
            iterator.remove();
        }
        mIsHeaderViewChecked = false;
        mIsFooterViewChecked = false;
        notifyDataSetChanged();
    }

    private int getDataCount() {
        if (isHeaderAndFooterAdapter()) {
            return getHeaderAndFooterAdapter().getDataCount();
        }
        return getItemCount();
    }

    private int getRealPosition(int dataPosition) {
        if (isHeaderAndFooterAdapter() && getHeaderAndFooterAdapter().hasHeaderView()) {
            return dataPosition + 1;
        }
        return dataPosition;
    }

    private int getDataPosition(int realPosition) {
        if (isHeaderAndFooterAdapter() && getHeaderAndFooterAdapter().hasHeaderView()) {
            return realPosition - 1;
        }
        return realPosition;
    }

    private int getOldChoicePosition() {
        int position = -1;
        for (int pos : mChoicePositions) {
            position = pos;
        }
        return position;
    }

    private boolean isHeaderAndFooterAdapter() {
        return mOriginalAdapter instanceof HeaderAndFooterAdapter;
    }

    private HeaderAndFooterAdapter getHeaderAndFooterAdapter() {
        return (HeaderAndFooterAdapter) mOriginalAdapter;
    }

    public void setHeaderView(OnViewCreateListener headerViewCreateListener) {
        if (!isHeaderAndFooterAdapter()) {
            throw new RuntimeException("没有嵌套HeaderAndFooterAdapter");
        }
        if (getHeaderAndFooterAdapter().getHeaderViewCreateListener() == headerViewCreateListener) {
            return;
        }
        if (getHeaderAndFooterAdapter().getHeaderViewCreateListener() == null) {
            getHeaderAndFooterAdapter().setHeaderView(headerViewCreateListener);
            notifyItemInserted(0);
            return;
        }
        if (headerViewCreateListener == null) {
            getHeaderAndFooterAdapter().setHeaderView(null);
            notifyItemRemoved(0);
            return;
        }
        getHeaderAndFooterAdapter().setHeaderView(headerViewCreateListener);
        notifyItemChanged(0);
    }

    public void setFooterView(OnViewCreateListener footerViewCreateListener) {
        if (!isHeaderAndFooterAdapter()) {
            throw new RuntimeException("没有嵌套HeaderAndFooterAdapter");
        }
        if (getHeaderAndFooterAdapter().getFooterViewCreateListener() == footerViewCreateListener) {
            return;
        }
        if (getHeaderAndFooterAdapter().getFooterViewCreateListener() == null) {
            getHeaderAndFooterAdapter().setFooterView(footerViewCreateListener);
            notifyItemInserted(getItemCount() - 1);
        }
        if (footerViewCreateListener == null) {
            getHeaderAndFooterAdapter().setFooterView(null);
            notifyItemRemoved(getItemCount());
        }
        getHeaderAndFooterAdapter().setFooterView(footerViewCreateListener);
        notifyItemChanged(getItemCount() - 1);
    }

    @Override
    public int getItemCount() {
        return mOriginalAdapter.getItemCount();
    }

    @Override
    public int getItemViewType(int position) {
        return mOriginalAdapter.getItemViewType(position);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return mOriginalAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        if (mChoiceMode != CHOICE_MODE_NONE) {
            if (isHeaderAndFooterAdapter() && getHeaderAndFooterAdapter().isHeaderView(position)) {
                if (holder.itemView.isSelected() != mIsHeaderViewChecked) {
                    holder.itemView.setSelected(mIsHeaderViewChecked);
                }
            } else if (isHeaderAndFooterAdapter() && getHeaderAndFooterAdapter().isFooterView(position)) {
                if (holder.itemView.isSelected() != mIsFooterViewChecked) {
                    holder.itemView.setSelected(mIsFooterViewChecked);
                }
            } else {
                if (mChoicePositions.contains(getDataPosition(position))) {
                    if (!holder.itemView.isSelected()) {
                        holder.itemView.setSelected(true);
                    }
                } else if (holder.itemView.isSelected()) {
                    holder.itemView.setSelected(false);
                }
            }
        }
        mOriginalAdapter.onBindViewHolder(holder, position);
    }

    @Override
    public long getItemId(int position) {
        return mOriginalAdapter.getItemId(position);
    }
}
